package com.cn.auth.enums;


import com.cn.auth.constant.ResponseCodeFace;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public enum ResponseCodeEnum implements ResponseCodeFace {
    SC(0, "操作成功", "操作成功"),
    SC200(200, "操作成功", "操作成功"),
    FAIL(1, "操作失败", "操作失败"),
    FAIL2(-1, "操作失败", "操作失败"),

    PARAM_LOSE(101, "缺少参数,参数： [${0}] 不存在或者为null", "参数异常"),
    PARAM_ILLEGAL(102, "参数中存在非法数据,参数：[${0}] 值为： [${1}]无法被识别", "参数异常"),
    PARAM_ILLEGAL2(103, "参数中存在非法数据,参数：[${0}] 值为： [${1}] 无法被识别，应该是 [${2}] 中的一个", "参数异常"),
    PARAM_LONG_SIMPLE(104, "参数过长，请检测长度", "参数异常"),
    PARAM_LOSE_SIMPLE(105, "缺少必要参数", "参数异常"),
    PARAM_CAST_SIMPLE(107, "参数类型转换出错", "参数异常"),
    PARAM_CAST2(108, "参数类型转换出错 , ${0} 类型值为： ${1} , 无法转换为类型${2}", "参数异常"),
    PARAM_ILLEGAL_SIMPLE(109, "非法参数", "参数异常"),
    PARAM_ILLEGAL3(110, "非法参数 --> ${0}", "参数异常"),

    PARAM_VALIDATOR(111, "${1} --> 校验不通过[${0}]", "参数异常"),

    PARAM_EXCEPTION(199, "参数型无法定义异常", "参数异常"),

    CONFIG_LOSE(801, "没有找到对应的配置", "配置异常"),
    CONFIG_ILLEGAL(802, "能找到配置，但无法使用", "配置异常"),
    CONFIG_EXCEPTION(899, "配置型无法定义异常", "配置异常"),


    ACCOUNT_PASSWORD(301, "账号密码错误","账号和密码不匹配"),
    ACCOUNT_ILLEGAL(302, "没有此账号","此账号不存在"),
    ACCOUNT_ABNORMAL(303, "此账号异常，可能存在风险","此账号异常，麻烦更换账号重试"),
    ACCOUNT_PERMISSIONS(304, "权限不足","权限不足"),
    ACCOUNT_PORTAL_LOCK(305, "您的账号由于登录过于频繁，已经被系统锁定，请15分钟之后再试","登录过于频繁"),
    ACCOUNT_LOCK(305, "您的账号由于登录过于频繁，已经被系统锁定，请${0}分钟之后再试","登录过于频繁"),

    ACCOUNT_USERNAME_ERR(306, "用户名不存在！","用户名不存在"),
    ACCOUNT_LOGOUT_ERR(307, "注销失败！","注销失败，请稍后重试"),
    ACCOUNT_EXCEPTION(399, "配置型无法定义异常","配置类型有误"),

    FILE_LARGE(401, "文件过大","文件过大，暂无法处理"),
    FILE_DOWNLOAD(402, "文件下载失败","文件下载失败"),
    FILE_LOCK(403, "文件被锁，无法处理","文件被锁定"),
    FILE_NAME_LONG(404, "文件名过长","文件名过长"),
    FILE_UPLOAD(405, "上传失败","上传失败"),
    FILE_BAD(406, "上传文件损坏","文件可能损坏"),
    FILE_EXITS(407, "系统已存在相同文件","文件重复啦"),
    FILE_UPLOADING(408, "已存在相同文件正在上传","已有相关文件正在上传，请检查是否重复"),
    FILE_DATA(409, "文件数据错误","系统暂时无法解析当前文件"),
    FILE_CHUNK_COUNT(4, "切片数出错","切片数不正确"),
    FILE_SIZE(411, "切片文件大小错误","切片文件大小有误"),
    FILE_EXCEPTION(499, "文件类型无法定义异常","系统无法识别这类文件"),


    TOKEN_FAILURE_ERR(2301, "token已失效","登录超时，需重新登录"),
    TOKEN_USER_ERR(502, "获取用户信息失败","暂无法获取用户信息"),
    TOKEN_INVALID_ERR(503, "请传入有效的token","登录信息验证不通过"),
    TOKEN_REFRESH_ERR(504, "token:[${0}]不存在！","登录信息验证不通过"),

    ACCESS_DENIED(601, "无法访问","无法访问"),
    ACCESS_LOCK_OTH(602, "无法获得锁", "当前数据被其他人锁定"),
    ACCESS_TO_FAST(603, "请求过于频繁","操作太快了，敬请稍等1分钟"),

    /**
     * DUBBO_UNKOWN的code不能被修改，切记，一定是只能700，不然就是701，702，703往上拍，
     * dubbo的700-705的错误码，是根据RpcException的code排列的，如果有自定义的dubbo异常，
     * 请设置不会和RpcException.code冲突的code
     */
    DUBBO_UNKNOWN(700, "DUBBO-调用${0}发生,未知异常","Dubbo接口调用失败"),
    DUBBO_NETWORK(701, "DUBBO-发调用${0}发生,生网络异常","DUBBO接口调用失败"),
    DUBBO_BIZ_EXCEPTION(702, "DUBBO-调用${0}发生,业务异常","Dubbo接口调用失败"),
    DUBBO_TIMEOUT(703, "DUBBO-调用${0}发生,链接超时","Dubbo接口调用失败"),
    DUBBO_FORBIDDEN(704, "DUBBO-调用${0}发生,非法的provider，或者服务已下线，或进入黑名单","Dubbo接口调用失败"),
    DUBBO_SERIALIZATION(705, "DUBBO-调用${0}发生,序列化异常","Dubbo接口调用失败"),

    SQL_UNKNOWN(800, "数据库处理异常", "数据库异常"),
    SQL_SIZE_ERR_SIM(801, "查询结果返回异常", "数据库异常"),
    SQL_SIZE_ERR2(802, "查询结果返回异常，目标是 1 条 ，实际返回 ${0} 条", "数据不存在"),
    SQL_DATA_LONG(803, "插入数据库字段过  ${0}  过长", "数据库异常"),
    SQL_INDEX_ERR(804, "数据插入时，违反索引", "数据库异常"),
    SQL_DATA_EXPIRED(805,"数据已失效","数据已被其他人更新"),

    JSON_UNKNOWN(900, "json异常", "json异常"),
    JSON_PARSE(901, "json解析异常", "json异常"),
    JSON_FORMAT(903, "json格式错误", "json异常"),
    JSON_NO_MATCH(903, "json中数据类型不匹配", "json异常"),


    BIZ_EXCEPTION(9900, "自定义异常","当前操作不成功"),
    UNKNOWN_ERR1(9901, "未知异常","当前操作不成功"),
    UNKNOWN_ERR2(9902, "未知异常:  ${0}","当前操作不成功"),

    BIZ_DATA_QUERY_EXCEPTION(9903, "数据查询出错：${0}","数据查询结果为空"),
    BIZ_DATA_NOT_EQUAL(9904, "数据一致性检查出错：${0}","数据一致性检查不通过"),
    BIZ_PROCESS_ERROR(9905, "调用流程引擎失败：${0}","流程相关接口网络不通"),
    BIZ_PROCESS_QUERY_ERROR(9906, "未查询到数据：${0}","未查询到数据"),
    BIZ_COLUMN_LOST(9907, "条件数据不全","筛选条件的判断值未填写完整"),
    GENERATE_CONTRACT_TO_FAST(9908,"当前合同${0}正在生成中...，请稍后一分钟","合同生成产物过于频繁"),
    BIZ_QR_CODE_EXPIRE(9909, "二维码已失效","二维码已失效")
    ;


    /**
     * 错误码
     */
    private int code;
    /**
     * 错误码描述
     */
    private String doc;
    /**
     * 比较友好的提示信息，
     */
    private String fMsg;

    ResponseCodeEnum(int code, String doc, String fMsg) {
        this.code = code;
        this.doc = doc;
        if (fMsg == null) {
            fMsg = ResponseCodeFace.fMsg;
        }
        this.fMsg = fMsg;

        registry2Global();
    }

    /**
     * 构造函数
     * @param code
     * @param doc
     */
    ResponseCodeEnum(int code, String doc) {
        this(code, doc, doc);
    }

    @Override
    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    @Override
    public String getDoc() {
        return doc;
    }


    public void setDoc(String doc) {
        this.doc = doc;
    }

    @Override
    public String getFMsg() {
        return fMsg;
    }

    public void setFMsg(String fMsg) {
        this.fMsg = fMsg;
    }

    /**
     * 根据Key得到枚举的Value
     * Lambda表达式，比较判断（JDK 1.8）
     *
     * @param key
     * @return
     */
    public static ResponseCodeEnum getEnumByKey(String key) {
        return getEnumByKey(Integer.valueOf(key));
    }

    /**
     * 根据Key得到枚举的Value
     * Lambda表达式，比较判断（JDK 1.8）
     *
     * @param key
     * @return
     */
    public static ResponseCodeEnum getEnumByKey(int key) {
        return Arrays.asList(ResponseCodeEnum.values()).stream()
                .filter(codeEnum -> codeEnum.getCode() == key)
                .findFirst().orElse(ResponseCodeEnum.UNKNOWN_ERR1);
    }


    @Override
    public String toString() {
        return "ResponseCodeEnum{" +
                "code=" + code +
                ", doc='" + doc + '\'' +
                ", fMsg='" + fMsg + '\'' +
                "} " + super.toString();
    }

    /**
     * 将错误码改成map
     */
    public static Map<Integer, String> getMap() {
        Map<Integer, String> map = new HashMap<>();
        Arrays.asList(ResponseCodeEnum.values()).forEach(responseCodeEnum -> {
            map.put(responseCodeEnum.code, responseCodeEnum.doc);
        });
        return map;


    }
}

